package platform;

import components.MDialog;
import pri.swg.Dragger;
import pri.swg.Slider;
import common.Constant;
import common.Singleton;
import view.Main;
import view.ViewControl;
import vo.Attr;
import vo.Mean;

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

/**
 * 属性选择面板上的属性栏或标签
 *
 * 采用失焦恢复原色的策略，所以不选中不能知道是否是“重要选项” 2019/01/20
 */
public class AttrOption extends JPanel {
    private static final long serialVersionUID = 1L;
    private static final String floor_divider = "‖";

    private ViewControl vc;
    private Main main;
    private JTextField field = new JTextField();
    private JLabel label;
    private String record = "";
    // FL = focus lost, FG = focus gained
    private Color fieldFL = Color.LIGHT_GRAY, fieldFG = Color.WHITE, labelFL = Color.BLACK, labelFG = Color.DARK_GRAY,
            labelTextFL = new Color(220, 225, 255), labelTextFG = Color.WHITE, importantColor = Color.red;
    private int page = 0, type;
    private Attr attr, r_attr;// 当前目录、根目录
    private String candidates[], path = "";// 候选词、当前所选词目录
    private Attr folders[]; // 当前显示的目录和候选
    private JPanel normal; // 通用的选择属性的面板

    static final int list_length = 6;

    private AttrOption() {
        vc = Singleton.vc();
        main = Singleton.main();
    }

    public AttrOption(Attr attr, int type, JPanel normal) {
        this();

        setAttr(attr);
        r_attr = attr;
        this.type = type;
        this.normal = normal;
        label = new JLabel(attr.getText());
        Font font = new Font(Constant.roundfaceName , Font.BOLD, 18);
        label.setFont(font);
        field.setFont(font);
        setLayout(new GridLayout(2, 1));
        add(label);
        add(field);
        label.setOpaque(true);
        label.setHorizontalAlignment(JLabel.CENTER);
        label.setForeground(labelTextFL);
        field.setBackground(fieldFL);
        label.setBackground(labelFL);
        field.setHorizontalAlignment(JTextField.CENTER);
        field.setBorder(null);
        field.setCaretColor(Color.LIGHT_GRAY);
        field.addFocusListener(new FocusAdapter() {
            public void focusLost(FocusEvent e) {
                field.setBackground(fieldFL);
                label.setBackground(labelFL);
                label.setForeground(labelTextFL);
            }
        });
        field.addKeyListener(new KeyAdapter() {// 输入监听
            boolean typedOver = false;

            public void keyTyped(KeyEvent e) {
                typedOver = true;
            }

            public void keyReleased(KeyEvent e) {
                if (typedOver && !record.equals(field.getText())) {
                    Singleton.main().confirmer.setVisible(true);
                    Singleton.main().occupier.setVisible(false);
                    typedOver = false;
                }
            }
        });
        field.addMouseListener(new MouseAdapter() {
            public void mouseReleased(MouseEvent e) {
                gainedFocus(false);
                showList();
            }
        });

        // 设置重要属性
        label.addMouseListener(new MouseAdapter() {
            boolean controlDown = false;
            public void mousePressed(MouseEvent e) {
                if (e.isControlDown()) {
                    controlDown = true;
                    if (e.getClickCount() == MouseEvent.BUTTON1) {
                        Mean.important_type = Mean.important_type == type ? -1 : type;
                    }
                }
            }

            public void mouseReleased(MouseEvent e) {
                field.requestFocus();// 获取焦点
                gainedFocus(controlDown);
                showList();
            }
        });
        Dragger.drag_VOH(main.attrSetter, label, Dragger.Vertical, 0, Constant.FHeight - 64);
    }
    private void gainedFocus(boolean controlDown) {
        field.setBackground(fieldFG);
        label.setBackground(labelFG);

        if (type == Mean.important_type) {
            label.setForeground(importantColor);
        } else
            label.setForeground(labelTextFG);

        if (controlDown) {
            vc.attr_addAll();
        }

        if (attr != r_attr)// error point:子目录翻页后，主目录没有对应的page页，显示错误
            page = 0;
        setAttr(r_attr);
    }

    public void showList() {
        if (attr.changed) {
            candidates = attr.getArray();// 若有更改则重新获取
            folders = attr.getFolders();
            attr.changed = false;
        }
        normal.setVisible(false);
        normal.removeAll();
        normal.add(new ALabel(this,true));// 先添加一个+按钮

        int fl = folders.length, cl = candidates.length, al = fl + cl, i;
        boolean turn = false;
        for (i = 0; i < list_length; i++) {
            if ((i + list_length * page) >= al)
                break;
            turn = (i + list_length * page) >= fl;
            normal.add(turn ? new ALabel(candidates[i + list_length * page - fl], this, vc)
                    : (new ALabel(folders[i + list_length * page], this)));
        }
        if (al == list_length + 1)
            normal.add(turn ? new ALabel(candidates[i - fl], this, vc) : (new ALabel(folders[i], this)));
        else if ((folders.length + candidates.length) > list_length + 1)
            normal.add(new ALabel(this,false));// 添加后翻按钮
        normal.setVisible(true);
    }

    public boolean existCandidate(String candidate) {
        return attr.getCandidate().contains(candidate);
    }

    public boolean existFolder(String name) {
        return attr.containsFolder(name);
    }

    public void refresh() {
        field.setText("");
        field.setBackground(fieldFL);
        label.setBackground(labelFL);
        label.setForeground(labelTextFL);
    }

    public void setRecord(String record) {
        this.record = record;
        field.setText(record);
    }

    void setFieldText(String text) {
        field.setText(text);
    }

    public String getFieldText() {
        return field.getText();
    }

    String[] getCandidates() {
        return candidates;
    }

    Attr[] getFolders() {
        return folders;
    }

    void setList(int list) {
        this.page = list;
    }

    int getList() {
        return page;
    }

    String getAttrPath() {
        return attr.getPath();
    }

    public Attr getAttr() {
        return attr;
    }

    void setAttr(Attr attr) {
        candidates = attr.getArray();
        folders = attr.getFolders();
        this.attr = attr;
    }

    void setPath() {
        if (attr.hasBoss()) {
            path = attr.getText() + floor_divider;
            Attr pre = attr, boss = pre.getBoss();
            while (boss != null) {
                if (boss.hasBoss())
                    path = boss.getText() + floor_divider + path;
                boss = boss.getBoss();
            }
        }
    }

    String getPath() {
        return path;
    }
}

class ALabel extends JLabel {
    private static final long serialVersionUID = 1L;
    private static final int BUTTON = 1, CANDY = 2, FOLDER = 3;
    private Font font = new Font(Constant.roundfaceName, Font.BOLD, 20);

    /**
     * @param type if it's a button
     */
    private ALabel(int type) {
        setForeground(type == BUTTON ? Color.CYAN : type == CANDY ? Color.BLACK : Color.YELLOW);// B
        setBackground(type == BUTTON ? Color.BLACK : type == CANDY ? Color.LIGHT_GRAY : Color.DARK_GRAY);// A
        setFont(font);
        setHorizontalAlignment(JLabel.CENTER);
        setOpaque(true);
        addMouseListener(new MouseAdapter() {
            public void mouseEntered(MouseEvent e) {
                setForeground(type == BUTTON ? getForeground() : type == CANDY ? Color.CYAN : Color.DARK_GRAY);// B1
                setBackground(type == BUTTON ? Color.BLACK : type == CANDY ? Color.white : Color.YELLOW);// A1
                setCursor(new Cursor(Cursor.HAND_CURSOR));
            }

            public void mouseExited(MouseEvent e) {
                setForeground(type == BUTTON ? getForeground() : type == CANDY ? Color.BLACK : Color.yellow);// B
                setBackground(type == BUTTON ? Color.BLACK : type == CANDY ? Color.LIGHT_GRAY : Color.DARK_GRAY);// A
                setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
            }
        });
    }

    /**
     * 候选词单元
     *
     * @param text
     *            文字
     * @param option
     *            依附的属性版
     */
    ALabel(String text, AttrOption option, ViewControl vc) {
        this(CANDY);
        setText(text);
        setToolTipText("右击弹收删除按钮");
        setLayout(null);
        ALabel delete = new ALabel(option, text, null);
        add(delete);
        Slider d_s = Slider.direct(delete, Slider.RIGHT, 32, 100, Slider.RETURN);
        addMouseListener(new MouseAdapter() {
            boolean gone = false;

            public void mouseReleased(MouseEvent e) {
                if (e.getButton() == MouseEvent.BUTTON1) {
                    option.setPath();
                    option.setFieldText(option.getPath() + text);
                    vc.showConfirmer(true);
                } else {
                    if (gone)
                        d_s.goBack();
                    else
                        d_s.goOn();
                    gone = !gone;
                }
            }
        });
    }

    /**
     * 候选词操作按键
     *
     * @param option
     *            候选词来源
     * @param isAdd
     *            是为添加，否则是后进
     */
    ALabel(AttrOption option, boolean isAdd) {
        this(BUTTON);
        addMouseListener(new MouseAdapter() {
            boolean have_rest = (option.getCandidates().length + option.getFolders().length
                    + -(option.getList() + 1) * AttrOption.list_length) > 0;
            {
                setText(isAdd ? "+候选词" : have_rest ? ">" : "<<");
                setToolTipText(isAdd ? "右击变更为 “+目录” 或 “+候选词”" : "");
            }
            int addtype = MDialog.ADD;

            public void mouseReleased(MouseEvent e) {
                if (e.getButton() == MouseEvent.BUTTON1) {
                    if (isAdd) {// 添加按钮
                        new MDialog(option.getAttrPath(), option, addtype);
                    } else if (have_rest) {// 下一页按钮
                        option.setList(option.getList() + 1);
                        option.showList();
                        have_rest = (option.getCandidates().length
                                - (option.getList() + 1) * AttrOption.list_length) > 0;
                        setText(have_rest ? "<<" : ">");
                    } else {// 返回按钮
                        option.setList(0);
                        option.showList();
                        have_rest = (option.getCandidates().length
                                - (option.getList() + 1) * AttrOption.list_length) > 0;
                        setText(have_rest ? "<<" : ">");

                    }
                } else {
                    if (isAdd) {// 右键切换添加按钮功能是添加候选词或目录
                        boolean add = addtype == MDialog.ADD;
                        addtype = add ? MDialog.ADD_FOLDER : MDialog.ADD;
                        setText(add ? "+目录" : "+候选词");
                        setForeground(add ? Color.YELLOW : Color.cyan);
                    }
                }
            }
        });
    }

    ALabel(Attr attr, AttrOption option) {
        this(FOLDER);
        setLayout(null);
        setText(attr.getText());
        setToolTipText("右击弹收删除按钮");
        ALabel delete = new ALabel(option, "", attr);
        add(delete);
        Slider d_s = Slider.direct(delete, Slider.RIGHT, 32, 100, Slider.RETURN);
        addMouseListener(new MouseAdapter() {
            boolean gone = false;

            public void mouseReleased(MouseEvent e) {
                if (e.getButton() == MouseEvent.BUTTON1) {
                    option.setAttr(attr);
                    option.setList(0);
                    option.showList();
                } else {
                    if (gone)
                        d_s.goBack();
                    else
                        d_s.goOn();
                    gone = !gone;
                }
            }
        });
    }

    /**
     * 删除候选词使用的红色叉号
     */
    private ALabel(AttrOption option, String text, Attr attr) {
        setBounds(-32, 0, 32, 32);
        setFont(font);
        setHorizontalAlignment(JLabel.CENTER);
        setText("×");
        setOpaque(true);
        setForeground(Color.white);
        setBackground(Color.RED);
        requestFocus();
        addMouseListener(new MouseAdapter() {
            public void mouseReleased(MouseEvent e) {
                if (e.getButton() == MouseEvent.BUTTON1) {
                    if (attr == null)
                        option.getAttr().delete(text);
                    else
                        option.getAttr().delete(attr);
                    option.setList(0);
                    option.showList();
                }
            }
        });
    }
}